#include "Zone.h"
#include "Planets.h"
#include "BossPlanets.h"
#include "../SGD Wrappers/SGD_Geometry.h"
#include <random>

void Zone::PopulatePlanets()
{
	//Allocate the zoneBoss
	zoneBoss = new BossPlanets;
	zoneBoss->SetSize({ 366, 366 });
	zoneBoss->CalculateRadius();
	zoneBoss->SetOwner(this);
	zoneBoss->SetPosition(this->GetRect().ComputeCenter());
	zoneBoss->SetWeakPoints();
	planets.push_back(zoneBoss);
	CalculateRadius();
	if (isFirst)
	{
		Planets* first = new Planets;
		first->SetSize({ 128, 128 });
		first->SetPosition({ position.x, position.y});
		first->CalculateRadius();
		first->SetPlanetType(Planets::PlanetType::SAND);
		planets.push_back(first);
	}

	//allocate the new planets
	for (int i = 0; i < numPlanets; i++)
	{
		std::random_device rd; //create the random device seed
		std::mt19937 mt(rd()); //create the random engine and seed it with the device

		int r = (int)GetRadius();

		int minX = (int)(this->GetRect().ComputeCenter().x - GetRadius()); //minimum x that the planet can be placed
		int maxX = (int)(this->GetRect().ComputeCenter().x + GetRadius()); //maximum x that the planet can be placed
		int minY = (int)(this->GetRect().ComputeCenter().y - GetRadius()); //minimum y that the planet can be placed
		int maxY = (int)(this->GetRect().ComputeCenter().y + GetRadius()); //maximum y that the planet can be placed

		std::uniform_int_distribution<int> randRadius(minPlanetRad,maxPlanetRad); //random radius generator for the new planet
		std::uniform_int_distribution<int> randXPos(minX, maxX); //random x position generator for the new planet
		std::uniform_int_distribution<int> randYPos(minY, maxY); //random y position generator for the new planet
		int radius = 64;//randRadius(mt); //random radius value for the new planet
		int xPos = randXPos(mt); //random x position value for the new planet
		int yPos = randYPos(mt); //random y position value for the new planet

		Planets* newPlanet = new Planets(); //allocate a new planet
		newPlanet->SetSize({ radius * 2.0f, radius * 2.0f }); //set the size of the new planet
		newPlanet->SetPosition({(float)xPos, (float)yPos}); //set the position of the new planet
		newPlanet->CalculateRadius();

		bool failed = false; //initialize the test failed variable;
		
		//test position against all existing planets
		for (unsigned int j = 0; j < planets.size(); j++)
		{
			SGD::Vector distance = planets[j]->GetRect().ComputeCenter() - newPlanet->GetPosition(); //distance between the planets
			float length = distance.ComputeLength(); //the length of that distance
			if (length < newPlanet->GetRadius() + planets[j]->GetRadius() + 200) //test if length is less than the two radii plus grapple distance
			{
				failed = true; //if so, the position has failed
				delete newPlanet;
				break; //break out and start over
			}
		}
		if (!failed) //if the position is valid, place the planet into the vector
		{
			if (zType == ZONE1)
				newPlanet->SetPlanetType(Planets::PlanetType::SAND);
			else if (zType == ZONE2)
				newPlanet->SetPlanetType(Planets::PlanetType::FOREST);
			else if (zType == ZONE3)
				newPlanet->SetPlanetType(Planets::PlanetType::ICE);
			else if (zType == ZONE4)
				newPlanet->SetPlanetType(Planets::PlanetType::LAVA);
			else if (zType == ZONE5)
				newPlanet->SetPlanetType(Planets::PlanetType::SHADOW);

			planets.push_back(newPlanet);
		}
	}
}

void Zone::AddAsteroid(Planets* p)
{
	if (zType == ZONE1)
		p->SetPlanetType(Planets::PlanetType::ASTD_SAND);
	else if (zType == ZONE2)
		p->SetPlanetType(Planets::PlanetType::ASTD_FOREST);
	else if (zType == ZONE3)
		p->SetPlanetType(Planets::PlanetType::ASTD_ICE);
	else if (zType == ZONE4)
		p->SetPlanetType(Planets::PlanetType::ASTD_LAVA);
	else if (zType == ZONE5)
		p->SetPlanetType(Planets::PlanetType::ASTD_SHADOW);

	asteroids.push_back(p);
}

void Zone::ReleasePlanets()
{
	for (unsigned int i = 0; i < zoneBoss->GetWeakPoints().size(); i++)
		zoneBoss->GetWeakPoints()[i]->Release();
	for (unsigned int i = 0; i < planets.size(); i++)
		planets[i]->Release();
	if (0 < asteroids.size())
	{
		for (unsigned int i = 0; i < asteroids.size(); i++)
			asteroids[i]->Release();
	}
	planets.clear();
	asteroids.clear();
}